package portal.common;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.concurrent.TimeUnit;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShellExec{ 
	private static final boolean FramWork=true;
	//private static final boolean FramWork=false;
	private static final Logger logger = LoggerFactory.getLogger(ShellExec.class);
	public static Boolean callShell(String shellString,String resultKey) {
		logger.debug("*************************************cmd:{}", shellString);
		//Boolean result = Boolean.valueOf(true);
		if(FramWork)
			return processExe(shellString,resultKey);
		
		try{
			Process process = null;
			//System.out.println(shellString);
			process = Runtime.getRuntime().exec(shellString);			
			return processExe(process ,resultKey);			
		} catch (IOException e){
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return false;
	}
	public static Boolean callShell(String[] cmd ,String resultKey)	{
		logger.debug("*************************************cmd:{}", cmd.toString());
		if(FramWork)
		return processExe(cmd,resultKey);
		Process process = null;
		try{
			process = Runtime.getRuntime().exec(cmd);
			return processExe(process ,resultKey);				
		} catch (IOException e){
			e.printStackTrace();			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return false;
	}
	//@SuppressWarnings("unused")
	private static  boolean processExe(Process process,String resultKey) throws IOException, InterruptedException{
		printMessage(process,process.getErrorStream(),resultKey);
		printMessage(process,process.getInputStream(),resultKey);
		//inputMessage(process.getOutputStream(),process);
		/*BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
		StringBuilder line = new StringBuilder("");
		String ln = "";
		boolean hasResultKey=false;
		while ((ln = input.readLine()) != null) {
			System.out.println(ln.length());
			line.append(ln);
			if(resultKey!=null){
				if(ln.contains(resultKey))
					hasResultKey=true;
			}
			System.out.println(ln);
		}
		input.close();
		
		logger.debug("*****************************************process Input:{}", line);
		System.out.println(line);
		System.out.println(line.length());*/
		
		boolean res=process.waitFor(30,TimeUnit.SECONDS);
		if(res==false){
			//System.out.println("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
			//process.
			process.destroy();
			return false;
		}			
		process.destroy();
		//System.out.println("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC");
		/*if(resultKey!=null)
			return hasResultKey;*/
		//System.out.println(resultKey);
		return true;
	}
	public static Boolean callShell(String cmd){
		return callShell(cmd,null);
	}
	public static Boolean callShell(String[] cmd){
		return callShell(cmd,null);
	}
	private static void printMessage(final Process process ,final InputStream input,String resultKey) {
	   Thread  t =new Thread(new Runnable() {
	      public void run() {
	        InputStreamReader reader = new InputStreamReader(input);
	        BufferedReader bf = new BufferedReader(reader);
	        OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
	        BufferedWriter bw = new BufferedWriter(writer);
	        String line = null;
	        try{
	            while(process.isAlive()) {
	            	line=bf.readLine();
	            	if(line==null)
	            			TimeUnit.SECONDS.sleep(1);
	            	//logger.info(line);
	            	//System.out.println("cmd:     "+line);
	            	if(line.contains("[y/n]")){
	            				bw.write("y");
	            				bw.newLine();
	            		}
	            	}
	        } catch (IOException e) {
	            e.printStackTrace();
	       } catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        }
	    });
	   t.start();
	}
	//@SuppressWarnings("unused")
	@SuppressWarnings("unused")
	private static void inputMessage(final OutputStream output,final Process process){
		new Thread(new Runnable() {
		      public void run() {
		        OutputStreamWriter writer = new OutputStreamWriter(output);
		        BufferedWriter bw = new BufferedWriter(writer);
		        //String line = null;
		        try{
			        	while(process.isAlive()){
			            bw.write("y");
			            bw.newLine();
			            TimeUnit.SECONDS.sleep(3);;
			            }
		        } catch (IOException e) {
		            e.printStackTrace();
		         	} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		        }
		    }).start();
	}
	private static void inputMessage(final OutputStream output,final ExecuteWatchdog wa){
		new Thread(new Runnable() {
		      public void run() {
		        OutputStreamWriter writer = new OutputStreamWriter(output);
		        BufferedWriter bw = new BufferedWriter(writer);
		        //String line = null;
		        try{
			        	while(wa.isWatching()){
			            bw.write("y");
			            bw.newLine();
			            TimeUnit.SECONDS.sleep(3);;
			            }
		        } catch (IOException e) {
		            e.printStackTrace();
		         	} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		        }
		    }).start();
	}
	/***
	 * 重载的方法
	 * ***/
	//@SuppressWarnings("unused")
	private static boolean processExe(String[] cmd ,String resultKey){
		String command="";
		for(String c:cmd){
			command+=" "+c;
		}
		return processExe(command,resultKey);
	}
	/***
	 * 重载的方法
	 * ***/
	private static boolean processExe(String cmd,String resultKey){
		String out=command(cmd);
		//System.out.print(out);
		if(resultKey==null)
			return true;
		if(out.contains(resultKey))
			return true;
		return false;
	}
	
	/***
	 * common-exec 执行命令行
	 * @param command 要执行的命令
	 * @return 返回命令行输出的内容。
	 * **/
	public static String command(String command) {
        try {
            //String command = "ping "+ip;
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
            ByteArrayInputStream inputStream =new ByteArrayInputStream("y".getBytes());
            CommandLine commandline = CommandLine.parse(command);
            DefaultExecutor exec = new DefaultExecutor();
            ExecuteWatchdog watchdog = new ExecuteWatchdog(20*1000);//等待60秒，超时推出
            exec.setExitValue(1);
            PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream,errorStream,inputStream);
            exec.setWatchdog(watchdog);
            ///System.out.println("commandline:"+commandline);
            exec.setStreamHandler(streamHandler);
            DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
            //streamHandler
            //watchdog.
            exec.execute(commandline,resultHandler);
            inputMessage(outputStream,watchdog);
            //outputStream.write("y\r".getBytes());
            
            resultHandler.waitFor(60000);
            //inputStream.
            //exec.getStreamHandler().
            String out = outputStream.toString("gbk");
            String error = errorStream.toString("gbk");
//            System.out.println(error);
//            System.out.println(out);
//            System.out.println("--> Watchdog is watching ? " + watchdog.isWatching());
//            //watchdog.destroyProcess();//终止进程
//            //System.out.println("--> destroyProcess done.");
//            System.out.println("--> Watchdog is watching ? " + watchdog.isWatching());
//            System.out.println("--> Watchdog should have killed the process : " + watchdog.killedProcess());
//            System.out.println("--> wait result is : " + resultHandler.hasResult());
//            System.out.println("--> exit value is : " + resultHandler.getExitValue());
//            System.out.println("--> exception is : " + resultHandler.getException());
//            exit
//            if(exit==0)
//            		System.out.println("exit(0)");
//            else 
//            	System.out.println("exit("+exit+")");
            //System.out.println(out+error);
            return out+error;
        } catch (Exception e) {
            logger.error("ping task failed.",e);
            return e.getMessage();
        }
    }
}